package com.zs.letcode.top_interview_question_medium;

import java.util.LinkedList;
import java.util.Queue;

/**
 * 填充每个节点的下一个右侧节点指针
 * 给定一个完美二叉树，其所有叶子节点都在同一层，每个父节点都有两个子节点。二叉树定义如下：
 * <p>
 * struct Node {
 * int val;
 * Node *left;
 * Node *right;
 * Node *next;
 * }
 * 填充它的每个 next 指针，让这个指针指向其下一个右侧节点。如果找不到下一个右侧节点，则将 next 指针设置为 NULL。
 * <p>
 * 初始状态下，所有next 指针都被设置为 NULL。
 * <p>
 * 进阶：
 * <p>
 * 你只能使用常量级额外空间。
 * 使用递归解题也符合要求，本题中递归程序占用的栈空间不算做额外的空间复杂度。
 * 示例：
 * <p>
 * <p>
 * <p>
 * 输入：root = [1,2,3,4,5,6,7]
 * 输出：[1,#,2,3,#,4,5,6,7,#]
 * 解释：给定二叉树如图 A 所示，你的函数应该填充它的每个 next 指针，以指向其下一个右侧节点，如图 B 所示。序列化的输出按层序遍历排列，
 * 同一层节点由 next 指针连接，'#' 标志着每一层的结束。
 * 提示：
 * <p>
 * 树中节点的数量少于4096
 * -1000 <= node.val <= 1000
 * 相关标签
 * 树
 * 深度优先搜索
 * 广度优先搜索
 * 二叉树
 * <p>
 * 作者：力扣 (LeetCode)
 * 链接：https://leetcode-cn.com/leetbook/read/top-interview-questions-medium/xvijdh/
 * 来源：力扣（LeetCode）
 * 著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。
 *
 * @author madison
 * @description
 * @date 2021/10/11 11:33
 */
public class Chapter13 {

    public static void main(String[] args) {

    }

    private class Node {
        public int val;
        public Node left;
        public Node right;
        public Node next;

        public Node() {
        }

        public Node(int _val) {
            val = _val;
        }

        public Node(int _val, Node _left, Node _right, Node _next) {
            val = _val;
            left = _left;
            right = _right;
            next = _next;
        }
    }

    private class Solution {
        /**
         * 方法一：层次遍历
         *
         * @param root
         * @return
         */
        public Node connect(Node root) {
            if (root == null) {
                return root;
            }

            // 初始化队列同时将第一层节点加入队列中，即根节点
            Queue<Node> queue = new LinkedList<>();
            queue.add(root);

            // 外层的 while 循环迭代的是层数
            while (!queue.isEmpty()) {
                // 记录当前队列大小
                int size = queue.size();

                // 遍历这一层的所有节点
                for (int i = 0; i < size; i++) {
                    // 从队首取出元素
                    Node node = queue.poll();

                    // 连接
                    if (i < size - 1) {
                        node.next = queue.peek();
                    }

                    // 拓展下一层节点
                    if (node.left != null) {
                        queue.add(node.left);
                    }
                    if (node.right != null) {
                        queue.add(node.right);
                    }
                }
            }

            // 返回根节点
            return root;
        }

        /**
         * 方法二：使用已建立的 next 指针
         */
        public Node connect1(Node root) {
            if (root == null) {
                return null;
            }

            // 从根节点开始
            Node leftmost = root;
            while (leftmost.left != null) {
                // 遍历这一层节点组织成的链表，为下一层的节点更新 next 指针
                Node head = leftmost;
                while (head != null) {
                    // CONNECTION 1
                    head.left.next = head.right;

                    // CONNECTION 2
                    if (head.next != null) {
                        head.right.next = head.next.left;
                    }

                    // 指针向后移动
                    head = head.next;
                }

                // 去下一层的最左的节点
                leftmost = leftmost.left;
            }
            return root;
        }
    }
}
